2025-04-27 IPSec zwischen LANCOM-Router und strongSwan auf Alpine Linux

IPSec IKEv2 VPN zwischen LANCOM (LCOS) und Alpine Linux mit strongSwan.
Versionen zum Schreibzeitpunkt: LCOS 10.90.0221RU3, Alpine Version 3.21.3, strongswan-5.9.14-r0
strongSwan
Es passt irgendwie zu IPSec, das nicht nur die dazugehörigen Protokolle, sondern auch die Softwarelandschaft komplex ist. So gibt es mit strongSwan eine umfangreiche “IPSec-Implementierung” für Linux, die mit mehreren Daemons und inkompatiblen Konfigurationsdateien daher kommt. Sucht man nach Beispielen, wird oft von ipsec.conf geredet und von einem ipsec-Daemon. Hey, das klingt wie die VPN-Technik die man verwenden möchte. Aber Achtung: Die Datei und dazugehörige Syntax ist seit mehreren Jahren abgekündigt/deprecated und soll mit 6.0 komplett verschwinden. Mit strongswan.conf und swanctl.conf gibt es eine neue Konfigurationssyntax und mit charon einen ipsec ersetzenden Daemon.Anderes als ich es von OpenBSD-Projekten gewöhnt bin, wo inkompatible Konfigurationsänderungen - sehr gut erklärt - kurz und schmerzlos durchgedrückt werden, laufen bei strongSwan und den Linux-Distributionen die beiden System seit Jahren parallel. So hatte es z.B. peinlich lange gedauert, bis ich kapiert hatte, das die neue Konfig von einem anderen Daemon verarbeitet werden muss. Das Ding heiß "ipsec" verdamt. Woher kann ich wissen das man da was ganz anderes braucht. ;-)
Wie dem auch sei, diese Anleitung beschreibt nur das “moderne” Vorgehen. (Mal davon ab, dass keine Systemd Distro verwendet wird.)
Authentifizierung mit Pre-Shared Key (PSK)
Auf dem LANCOM ganz normal einen Einwahl-VPN-Zugang anlegen. Der “Fully Qualified Username” muss dem Format einer Email entsprechen und ist dabei das, was später in der swanctl.conf die local- und remote-id sein wird.Auf Alpine:
# apk add strongswan
# vim /etc/swanctl/conf.d/lancom-buero.conf
connections {
buero {
version = 2
proposals = aes256-sha256-ecp512bp
encap = yes
dpd_delay = 60s
remote_addrs = vpn.example.com
vips = 0.0.0.0
children {
buero {
esp_proposals = aes256-sha256-ecp512bp
start_action = start
dpd_action = restart
close_action = start
updown = doas /usr/lib/strongswan/_updown iptables
remote_ts = 198.51.100.0/24
#mobike = no # bei LCOS <10.90 Systemen auskommentieren
}
}
local {
auth = psk
id = sw@example
}
remote {
auth = psk
id = sw@example
}
}
}
secrets {
ike-sw {
id = sw@example
secret = "Passwort"
}
}
#eof
# chmod 600 /etc/swanctl/conf.d/lancom-buero.conf
Komplett optional, für weniger Meldungen im Syslog.
# vim /etc/strongswan.d/lancom-logging.conf
charon {
syslog {
identifier = charon
daemon {
enc = -1
net = -1
}
}
}
#eof
Falls Firewall im Einsatz:
# vim /etc/doas.d/charon.conf
# IPSec deamon charon
permit nopass keepenv ipsec as root cmd /usr/lib/strongswan/_updown args iptables
#eof
VPN-Verbindung starten:
# rc-service charon start
Automatisch beim booten starten:
# rc-update add charon
“encap = yes” Ohne verarbeitet Linux eingehende, in UDP gekapselte, ESP-Pakete nicht. ¯\_(ツ)_/¯“remote_addrs = vpn.example.com” Domain des LANCOM-Routers. Trotz AAAA-Record wird sich mit IPv4 verbunden. Grund hab ich bisher nicht weiter analysiert. Evtl. folgt dazu später ein Update.
“remote_ts = 198.51.100.0/24” Das entfernte Netzwerk, in das man will.
“vips = 0.0.0.0” Der Client erhält eine IP vom VPN-Router zugewiesen.
“secret = "Passwort"” Das Shared Secret, der Preshared Key. Wenn die Zeichenkette ein Anführungszeichen enthält, muss diese Base64 kodiert werden. (Zusammen mit einer 0s Makierung). Dazu dieser Einzeiler:
SWB64P=`mktemp` && base64 > $SWB64P && echo && echo 0s`cat $SWB64P` && rm $SWB64P
Wichtig: Nach der Passworteingabe nicht Enter drücken, sondern dreimal Strg + d. Andernfalls wird der Zeilenumbruch mitkodiert und die Authentifizierung wird scheitern. Der Einzeiler ist nur auf Busybox getestet.
Authentifizierung mit Zertifikat
Wie man eine CA erstellt und den LANCOM-Router dafür konfiguriert, habe ich in meinem OpenSSL-Spickzettel beschrieben:openssl.txt
openssl_Beispiel.cnf
Einfach dem Beispiel "Android mit strongSwan" folgen. Der Weg ist mehr oder weniger der Gleiche.
Auf Alpine:
Mit Cert- und Key-File:
# cp ORGANIZATION_CACert.pem /etc/swanctl/x509ca/
# cp ClientXYZ-FQDN_Cert.pem /etc/swanctl/x509/
# cp ClientXYZ-FQDN_Key.pem /etc/swanctl/private/
# chmod 400 /etc/swanctl/private/ClientXYZ-FQDN_Key.pem
# vim /etc/swanctl/conf.d/lancom-buero.conf
connections {
buero {
version = 2
proposals = aes256-sha256-ecp512bp
encap = yes
dpd_delay = 60s
remote_addrs = vpn.example.com
vips = 0.0.0.0
children {
buero {
esp_proposals = aes256-sha256-ecp512bp
start_action = start
dpd_action = restart
close_action = start
updown = doas /usr/lib/strongswan/_updown iptables
remote_ts = 198.51.100.0/24
#mobike = no # bei LCOS <10.90 Systemen auskommentieren
}
}
local {
auth = pubkey
certs = ClientXYZ-FQDN_Cert.pem
}
remote {
cacerts = ORGANIZATION_CACert.pem
}
}
}
#eof
Mit PKCS #12 Zertifikatcontainer:
# cp ORGANIZATION_CACert.pem /etc/swanctl/x509ca/
# cp ClientXYZ-FQDN_Cert_with_Key.p12 /etc/swanctl/pkcs12/
# openssl x509 -subject -noout -in ClientXYZ-FQDN_Cert_with_Key.p12
subject=C=DE, ST=Bavaria, O=example.com, OU=Example.com Certification Authority, CN=vpn.example.com, emailAddress=camaster@example.com
# vim /etc/swanctl/conf.d/lancom-buero.conf
...
local {
auth = pubkey
id = C=DE, ST=Bavaria, O=example.com, OU=Example.com Certification Authority, CN=vpn.example.com, emailAddress=camaster@example.com
}
remote {
cacerts = ORGANIZATION_CACert.pem
}
}
}
secrets {
pkcs12 {
file = ClientXYZ-FQDN_Cert_with_Key.p12
secret = "Passwort"
}
}
#eof
# chmod 400 /etc/swanctl/conf.d/lancom-buero.conf
Der secrets-Abschnitt ist optional. Ohne wird beim Starten des Daemon nach dem Passwort der p12-Datei gefragt.Wie üblich die Erinnerung das einzelne VPN-Verbindung von LCOS als eigene Gegenstellen betrachtet werden und evtl. in der Firewall weitere Freigaben für die Kommunikation untereinander benötigt werden.
Homepage